/****************************************************************************
   Copyright 2013 Stacy Doss

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
****************************************************************************/

%{

// Order is important here, DefParser.tab.h should be after any thing that defines
// %union components in DefParser.y
#include <vector>
#include <string>
#include "Def.h"
#include "DefParser.tab.h"

extern int line_number;
extern int quote_count;
extern int expect_orient;
extern int expect_in_or_out;
extern int expect_digit;
extern def::Def* root;

%}

%option noyywrap

%x VERSIONSTATE
%x QUOTESTATE
%x XYSTATE
%x HISTORYSTATE

%%

VERSION						{ BEGIN(VERSIONSTATE); return VERSION; }
<VERSIONSTATE>[0-9.]*[0-9]+ { BEGIN(INITIAL); 
							  yylval.s=strdup(yytext); 
							  return VERSIONSTRING; }
NAMESCASESENSITIVE			{ return NAMESCASESENSITIVE; } 
BUSBITCHARS					{ BEGIN(QUOTESTATE); return BUSBITCHARS; }
DIVIDERCHAR					{ BEGIN(QUOTESTATE); return DIVIDERCHAR; }
<QUOTESTATE>\"				{ quote_count++;
							  if (quote_count > 1) {
								quote_count = 0;
								BEGIN(INITIAL);
							  };
							  return QUOTE; }
DESIGN						{ return DESIGN; }
TECHNOLOGY					{ return TECHNOLOGY; }
UNITS						{ return UNITS; }
HISTORY						{ BEGIN(HISTORYSTATE); return HISTORY; }
PROPERTYDEFINITIONS			{ return PROPERTYDEFINITIONS; }
DIEAREA						{ return DIEAREA; }
ROWS						{ return ROWS; }
TRACKS						{ BEGIN(XYSTATE); return TRACKS; }
GCELLGRID					{ BEGIN(XYSTATE); return GCELLGRID; }
VIAS						{ return VIAS; }
REGIONS						{ return REGIONS; }
COMPONENTS					{ return COMPONENTS; } 
PINS						{ return PINS; }
PINPROPERTIES				{ return PINPROPERTIES; }
BLOCKAGES					{ return BLOCKAGES; }
SLOTS						{ return SLOTS; }
FILLS						{ return FILLS; }
SPECIALNETS					{ return SPECIALNETS; }
NETS						{ return NETS; }
SCANCHAINS					{ return SCANCHAINS; }
GROUPS						{ return GROUPS; } 
BEGINEXT					{ return BEGINEXT; } 
END							{ return END; }

ON							{ return ON; }
OFF							{ return OFF; }
INTEGER						{ return INTEGER; }
REAL						{ return REAL; }
STRING						{ return STRING; }

NEW							{ return NEW; }
\*							{ return STAR; }
TAPER						{ return TAPER; }
TAPERRULE					{ return TAPERRULE; }
NOSHIELD					{ return NOSHIELD; }
ROUTED						{ return ROUTED; }
RING						{ return RING; }
PADRING						{ return PADRING; }
BLOCKRING					{ return BLOCKRING; }
STRIPE						{ return STRIPE;}
FOLLOWPIN					{ return FOLLOWPIN;}
IOWIRE						{ return IOWIRE;}
COREWIRE					{ return COREWIRE;}
BLOCKWIRE					{ return BLOCKWIRE;}
BLOCKAGEWIRE				{ return BLOCKAGEWIRE;}
FILLWIRE					{ return FILLWIRE;}
DRCFILL						{ return DRCFILL;}
SHAPE						{ return SHAPE;}
SHIELD						{ return SHIELD;}

COMPONENTPIN				{ return COMPONENTPIN; }
SPECIALNET					{ return SPECIALNET; }
GROUP						{ return GROUP; }
RANGE						{ return RANGE; }
ROW							{ return ROW; }

DISTANCE					{ return DISTANCE; }
MICRONS						{ return MICRONS; }

<XYSTATE>X					{ BEGIN(INITIAL); return X; }
<XYSTATE>Y					{ BEGIN(INITIAL); return Y; }
DO							{ return DO; }
STEP						{ return STEP; }
LAYER						{ return LAYER; }

TYPE						{ return TYPE; }
FENCE						{ return FENCE; }
PATTERNNAME					{ return PATTERNNAME; }
GUIDE						{ return GUIDE; }
BY							{ return BY; }

EEQMASTER					{ return EEQMASTER; }
SOURCE						{ return SOURCE; }
NETLIST						{ return NETLIST; }
DIST						{ return DIST; }
USER						{ return USER; }
TIMING						{ return TIMING; }
FOREIGN						{ return FOREIGN; }
FIXED						{ return FIXED; }
COVER						{ return COVER; }
PLACED						{ return PLACED; }
UNPLACED					{ return UNPLACED; }
WEIGHT						{ return WEIGHT; }
REGION						{ return REGION; }
PROPERTY					{ return PROPERTY; }
	/* Not necessarily the best way to do this, however it is relativity straight forward.
	   Needed to catch the case where we want a "NAME" not an orientation.
	   We likely will move this to a function at some point. */
N							{ if (expect_orient) {expect_orient = 0; return N; }  else {yylval.s=strdup(yytext); return NAME;}}
S							{ if (expect_orient) {expect_orient = 0; return S; }  else {yylval.s=strdup(yytext); return NAME;}}
E							{ if (expect_orient) {expect_orient = 0; return E; }  else {yylval.s=strdup(yytext); return NAME;}}
W							{ if (expect_orient) {expect_orient = 0; return W; }  else {yylval.s=strdup(yytext); return NAME;}}
FN							{ if (expect_orient) {expect_orient = 0; return FN; } else {yylval.s=strdup(yytext); return NAME;}}
FS							{ if (expect_orient) {expect_orient = 0; return FS; } else {yylval.s=strdup(yytext); return NAME;}}
FE							{ if (expect_orient) {expect_orient = 0; return FE; } else {yylval.s=strdup(yytext); return NAME;}}
FW							{ if (expect_orient) {expect_orient = 0; return FW; } else {yylval.s=strdup(yytext); return NAME;}}
IN							{ if (expect_in_or_out) {expect_in_or_out = 0; return IN; } else {yylval.s=strdup(yytext); return NAME;}}
OUT							{ if (expect_in_or_out) {expect_in_or_out = 0; return IN; } else {yylval.s=strdup(yytext); return NAME;}}
1							{ if (expect_digit) {expect_digit = 0; return ONE;  } else {yylval.i=atoi(yytext); return INT;}}
0							{ if (expect_digit) {expect_digit = 0; return ZERO; } else {yylval.i=atoi(yytext); return INT;}}

NET							{ return NET; }
SPECIAL						{ return SPECIAL; }
DIRECTION					{ return DIRECTION; }
USE							{ return USE; }
INPUT						{ return INPUT; }
OUTPUT						{ return OUTPUT; }
INOUT						{ return INOUT; }
FEEDTHRU					{ return FEEDTHRU; }
SIGNAL						{ return SIGNAL; }
POWER						{ return POWER; }
GROUND						{ return GROUND; }
CLOCK						{ return CLOCK; }
TIEOFF						{ return TIEOFF; }
ANALOG						{ return ANALOG; }
SCAN						{ return SCAN; }
RESET						{ return RESET; }
ANTENNAPINPARTIALMETALAREA	{ return ANTENNAPINPARTIALMETALAREA; }
ANTENNAPINPARTIALMETALSIDEAREA	{ return ANTENNAPINPARTIALMETALSIDEAREA; }
ANTENNAPINPARTIALCUTAREA	{ return ANTENNAPINPARTIALCUTAREA; }
ANTENNAPINDIFFAREA			{ return ANTENNAPINDIFFAREA; }
ANTENNAMODEL				{ return ANTENNAMODEL; }
OXIDE1						{ return OXIDE1; }
OXIDE2						{ return OXIDE2; }
OXIDE3						{ return OXIDE3; }
OXIDE4						{ return OXIDE4; }
ANTENNAPINGATEAREA			{ return ANTENNAPINGATEAREA; }
ANTENNAPINMAXAREACAR		{ return ANTENNAPINMAXAREACAR; }
ANTENNAPINMAXSIDEAREACAR	{ return ANTENNAPINMAXSIDEAREACAR; }
ANTENNAPINMAXCUTCAR			{ return ANTENNAPINMAXCUTCAR; }

PIN							{ return PIN; }
SYNTHESIZED					{ return SYNTHESIZED; }
MUSTJOIN					{ return MUSTJOIN; }
SHIELDNET					{ return SHIELDNET; } 
VPIN						{ return VPIN; }
SUBNET						{ return SUBNET; }
XTALK 						{ return XTALK; }
NONDEFAULTRULE				{ return NONDEFAULTRULE; }
FREQUENCY					{ return FREQUENCY; }

COMMONSCANPINS				{ return COMMONSCANPINS; } 
PARTITION					{ return PARTITION; } 
MAXBITS						{ return MAXBITS; }
FLOATING					{ return FLOATING; }
ORDERED						{ return ORDERED; }
BITS						{ return BITS; }
START						{ return START; }
STOP						{ return STOP; }

VOLTAGE						{ return VOLTAGE; }
FIXEDBUMP					{ return FIXEDBUMP; }
ORIGINAL					{ return ORIGINAL; }
PATTERN						{ return PATTERN; }
BALANCED					{ return BALANCED; }
STEINER						{ return STEINER; }
TRUNK						{ return TRUNK; }
WIREDLOGIC					{ return WIREDLOGIC; } 
ESTCAP						{ return ESTCAP; }

COMPONENT					{ return COMPONENT; } 
PLACEMENT					{ return PLACEMENT; }
PUSHDOWN					{ return PUSHDOWN; }
RECT						{ return RECT; } 


\[                        { yylval.s=strdup(yytext); return LEFTBRACKET; }
\]                        { yylval.s=strdup(yytext); return RIGHTBRACKET; }
\{                        { yylval.s=strdup(yytext); return LEFTBRACE; }
\}                        { yylval.s=strdup(yytext); return RIGHTBRACE; }
\(                        { yylval.s=strdup(yytext); return LEFTPAREN; }
\)                        { yylval.s=strdup(yytext); return RIGHTPAREN; }
\<                        { yylval.s=strdup(yytext); return LEFTANGLE; }
\>                        { yylval.s=strdup(yytext); return RIGHTANGLE; }
\.                        { yylval.s=strdup(yytext); return PERIOD; }
\:                        { yylval.s=strdup(yytext); return COLON; }
\/                        { yylval.s=strdup(yytext); return BACKSLASH; }
\|                        { yylval.s=strdup(yytext); return PIPE; }
\+						  { return PLUS; }
\-						  { return MINUS; }
\;                        { return SEMI; }
\,                        { return COMMA; }

<QUOTESTATE>\[                        { yylval.s=strdup(yytext); return LEFTBRACKET; }
<QUOTESTATE>\]                        { yylval.s=strdup(yytext); return RIGHTBRACKET; }
<QUOTESTATE>\{                        { yylval.s=strdup(yytext); return LEFTBRACE; }
<QUOTESTATE>\}                        { yylval.s=strdup(yytext); return RIGHTBRACE; }
<QUOTESTATE>\(                        { yylval.s=strdup(yytext); return LEFTPAREN; }
<QUOTESTATE>\)                        { yylval.s=strdup(yytext); return RIGHTPAREN; }
<QUOTESTATE>\<                        { yylval.s=strdup(yytext); return LEFTANGLE; }
<QUOTESTATE>\>                        { yylval.s=strdup(yytext); return RIGHTANGLE; }
<QUOTESTATE>\.                        { yylval.s=strdup(yytext); return PERIOD; }
<QUOTESTATE>\:                        { yylval.s=strdup(yytext); return COLON; }
<QUOTESTATE>\/                        { yylval.s=strdup(yytext); return BACKSLASH; }
<QUOTESTATE>\|                        { yylval.s=strdup(yytext); return PIPE; }

<HISTORYSTATE>[^;]*		  {yylval.s=strdup(yytext); return RAWTEXT;}
<HISTORYSTATE>\;		  {BEGIN(INITIAL); return SEMI;}

\"[^\"]*\"                { yylval.s=strdup(yytext); return QSTRING; } 
[0-9]+                    { yylval.i=atoi(yytext);   return INT; }
[0-9]+\.[0-9]+            { yylval.f=atof(yytext);   return FLOAT; }
[_a-zA-Z0-9\-]*           { yylval.s=strdup(yytext); return NAME; }

[ \t\r]+                  /* eat up whitespace */

[\n]                      { line_number++; }

"/*""/"*([^*/]|[^*]"/"|"*"[^/])*"*"*"*/"  /* eat comments */

%%
